package com.xx;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.*;
import com.jayway.jsonpath.JsonPath;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * json 根据模板转换
 */
//@Component
@Slf4j
public class JsonAdapter {

    /**
     * 根据模板将json串转成指定格式json串
     *
     * @param template 模板
     * @param jsonData json数据
     * @return
     * @throws JsonProcessingException
     */
    public String transformByTemplate(String template, String jsonData) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        JsonNode jsonNode = mapper.readTree(template);

        this.parserJsonNode(jsonNode, jsonData);
        return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
    }

    /**
     * 解析当前节点的值
     *
     * @param jsonNode     当前节点
     * @param valueJsonStr 值字符串
     * @throws JsonProcessingException
     */
    private void parserJsonNode(JsonNode jsonNode, String valueJsonStr) throws JsonProcessingException {
        if (jsonNode.isObject()) {
            // 对象类型节点
            ObjectNode objectNode = (ObjectNode) jsonNode;
            Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();

            while (iter.hasNext()) {
                Map.Entry<String, JsonNode> entry = iter.next();
                String subKey = entry.getKey();
                JsonNode subNode = entry.getValue();

                if (subNode.isValueNode()) {
                    // 如果是值节点，则解析表达式
                    ValueNode subValueNode = (ValueNode) subNode;
                    JsonNode newNode = fetchAndBuildJsonNode(subKey, subValueNode, valueJsonStr);
                    objectNode.set(subKey, newNode);
                } else {
                    parserJsonNode(subNode, valueJsonStr);
                }
            }
        } else if (jsonNode.isArray()) {
            // 如果是数组类型节点，则组个解析子节点
            ArrayNode arrayNode = (ArrayNode) jsonNode;
            for (int i = 0; i < arrayNode.size(); i++) {
                parserJsonNode(arrayNode.get(i), valueJsonStr);
            }
        }
    }

    /**
     * 从response中解析 nodeKey 对应的值
     *
     * @param nodeKey      属性名称
     * @param valueNode    nodeKey对应的表达式
     * @param valueJsonStr 完整数据json串
     * @return
     * @throws JsonProcessingException
     */
    private JsonNode fetchAndBuildJsonNode(String nodeKey, ValueNode valueNode, String valueJsonStr)
            throws JsonProcessingException {

        String expression = valueNode.asText();
        log.info("{} -> {}", nodeKey, expression);

        if (Objects.nonNull(expression)) {

            // json path 表达式
            if (expression.startsWith("$")) {
                String mapping = null;

                // 解析规则mapping
                if (expression.contains(Util.MAPPING)) {
                    mapping = Util.fetchMapping(expression);
                    log.info("mapping:{}", mapping);
                }

                Map<String, String> transformMap = null;
                if (Objects.nonNull(mapping) && mapping.contains(Util.COLON)) {
                    expression = expression.replace(mapping, "");
                    transformMap = parseMapping(mapping);
                }

                // 设置值
                Object read = JsonPath.read(valueJsonStr, expression);
                if (read instanceof net.minidev.json.JSONArray) {
                    ObjectMapper mapper = new ObjectMapper();
                    net.minidev.json.JSONArray array = (net.minidev.json.JSONArray) read;

                    List<JsonNode> nodeList = new ArrayList<>();
                    for (Object item : array) {
                        if (item instanceof Map) {
                            String itemStr = mapper.writeValueAsString(item);
                            ObjectNode jsonNode = (ObjectNode) mapper.readTree(itemStr);

                            // 根据规则转换
                            if (Objects.nonNull(transformMap)) {
                                transformMap.forEach((k, v) -> {
                                    if (jsonNode.has(v)) {
                                        jsonNode.set(k, jsonNode.get(v));
                                    }
                                });
                            }

                            nodeList.add(jsonNode);
                        } else {
                            String itemStr = item.toString();
                            nodeList.add(new TextNode(itemStr));
                        }
                    }
                    return new ArrayNode(new JsonNodeFactory(false), nodeList);
                } else {
                    // 非array
                    log.debug("key:{} 非array，原样返回:{}", nodeKey, read);
                    return new TextNode(read.toString());
                }
            } else {
                // 非json path 表达式
                log.debug("key:{} 非json path表达式，原样返回：{}", nodeKey, expression);
            }
        }
        return valueNode;
    }

    /**
     * 解析属性映射
     * [mapping#categoryAlias:category,authorAlias:author]
     *
     * @param mapping 映射规则
     * @return
     */
    private Map<String, String> parseMapping(String mapping) {

        Map<String, String> hashMap = new HashMap<>();

        mapping = mapping.replace(Util.MAPPING, "").replace(Util.BRACKET, "");
        String[] split = mapping.split(Util.COMMA);
        for (String item : split) {
            String[] split1 = item.split(Util.COLON);
            hashMap.put(split1[0], split1[1]);
        }
        return hashMap;
    }
}
